package com.aviator.executor;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;
import com.googlecode.aviator.lexer.token.OperatorType;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.type.AviatorObject;
import com.googlecode.aviator.runtime.type.AviatorString;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author: Jiangxx
 * @Date: 2021/12/30
 * @Description: 重载运算符、编译表达式
 */
public class AviatorExecutor07 {

    public static void main(String[] args) {

        /**
         * 重载运算符"+"为字符串拼接
         */
        AviatorEvaluator.addOpFunction(OperatorType.ADD, new AbstractFunction() {

            @Override
            public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
                return new AviatorString(arg1.getValue(env).toString() + arg2.getValue(env).toString());
            }

            @Override
            public String getName() {
                return "+";
            }
        });
        System.out.println(AviatorEvaluator.exec("a+3",4)); //43
        System.out.println(AviatorEvaluator.exec("a+' litchiShell'","Hello"));// Hello litchiShell

        /**
         * 编译表达式
         */
        String expression = "a-(b-c)>100";
        // 编译表达式
        /* 编译后的结果你可以自己缓存, 也可以交给 Aviator 帮你缓存, AviatorEvaluator内部有一个全局的缓存池,
        如果你决定缓存编译结果, 可以通过: public static Expression compile(String expression, boolean cached) */
        Expression compiledExp = AviatorEvaluator.compile(expression, true);
        Map<String, Object> env = new HashMap<String, Object>();
        env.put("a", 100.3);
        env.put("b", 45);
        env.put("c", -199.100);
        // 执行表达式
        Boolean result = (Boolean) compiledExp.execute(env);
        System.out.println(result);  // false

        /**
         * compile方法可以将表达式编译成Expression的中间对象, 当要执行表达式的时候传入env并调用Expression的execute方法即可。
         * 表达式中使用了括号来强制优先级, 这个例子还使用了>用于比较数值大小, 比较运算符!=、==、>、>=、<、<=不仅可以用于数值,
         * 也可以用于String、Pattern、Boolean等等, 甚至是任何用户传入的两个都实现了java.lang.Comparable接口的对象之间。
         */

        /* 将cached设置为true即可, 那么下次编译同一个表达式的时候将直接返回上一次编译的结果。使缓存失效通过:
        * public static void invalidateCache(String expression) */
        AviatorEvaluator.invalidateCache(expression);
    }
}
